#include "Game.hpp"
#include <cassert>

#include "../engine/World.hpp"

#include "../engine/core/Time.hpp"
#include "../engine/core/FPS.hpp"

#include "object/Hud.hpp"
#include "../engine/renderer/Renderer.hpp"
#include "../engine/light/ShaderProgram.hpp"

#include "behaviour/PlayerBehaviour.h"
#include "behaviour/CameraBehaviour.h"

#include "../engine/input/KeyBinder.h"
#include "../engine/input/MouseClick.h"

#include "../engine/core/Global.h"

Game::Game()
    :	window(NULL), hud(NULL), updater(NULL), renderer(NULL), world(NULL), camera(NULL), light(NULL) {
    window = new sf::RenderWindow(sf::VideoMode(800, 600), "Collision Detection by Erwin Cavas & Dave Nieuwenhuijzen");     // get a window
    std::cout << "Init Glew" << glewInit() << std::endl;

    updater = new Updater();
    renderer = new Renderer(window);
    collisionDetector = new CollisionDetector();

    Global::setWindow(window);
}

Game::~Game() {
    world->getTree()->print("|");
}

void Game::build() {
    Player* player = new Player(glm::vec3(0.0, 0.0, 0.0));
    player->setHud(new Hud(player, window));
    Global::setPlayer(player);

    Camera* camera = new Camera();
    camera->setBehaviour(new CameraBehaviour(camera, player));
    Global::setCamera(camera);

    renderer->use(new ShaderProgram("game/assets/shaders/default.vs", "game/assets/shaders/default.fs"));
    world = LevelBuilder::getInstance()->loadLevel("game/assets/levels/level1");

    world->add(player);

    Global::setWorld(world);
}

void Game::run() {
    assert(window != NULL);
    assert(renderer != NULL);
    assert(world != NULL);

    running = true;

    while(running) {
        Time::getInstance()->update();
        FPS::getInstance()->update();
        control();

        if(running) {
            if(MouseClick::getInstance()->isTapped()) {
                world->selectedAsteroid = NULL;
                // Create ray from camera to clicked position
                CollisionRay* ray = MouseClick::getInstance()->rayCasting(*window);
                // Test the ray with the complete octree
                world->getTree()->intersectsRay(ray, world->selectedAsteroid);
            }

            world->accept(updater);
            //world->accept(collisionDetector);

            KeyBinder::getInstance()->update();
            MouseClick::getInstance()->update();

            world->accept(renderer);

            if(Global::getPlayer()->getHud()) {
                Global::getPlayer()->getHud()->draw();
            }

            window->display();
        }
    }
}

void Game::stop() {

}

void Game::control() {
    sf::Event event;

    while(window->pollEvent(event)) {
        if(event.type == sf::Event::Closed) {
            window->close();
            running = false; // running = false;
        }
    }
}
